package com.njzxw.fs.commonutil.imp;

import com.aliyun.oss.ClientBuilderConfiguration;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.*;
import com.njzxw.fs.commonutil.bean.FileBean;
import com.njzxw.fs.commonutil.bean.PartBean;
import com.njzxw.fs.commonutil.repository.BaseRep;
import com.njzxw.fs.commonutil.util.DateUtil;
import com.njzxw.fs.commonutil.util.FileHellp;
import com.njzxw.fs.commonutil.util.RedisUtil;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Service
public class AliyunOssImp extends OssUtilAbs {

    @Autowired
    private BaseRep baseRep;

    @Autowired
    private RedisUtil redisUtil;

    @Override
    public boolean connect() {
        return true;
    }

    @Override
    public FileBean saveTemp(InputStream inputStream, String name, long size) {
        return super.saveTemp(inputStream, name, size,"");
    }

    @Override
    public FileBean saveTemp(InputStream inputStream, String name, long size,String md5) {

        FileBean fileBean = exeName(name, size);
        logger.debug("fileBean:"+fileBean);
        if (fileBean == null) {
            logger.warn("文件丢失");
            return null;
        }

        //校验md5值是否已存在临时文件，如存在直接返回


        String filesdir = DateUtil.getToday("yyyyMMddHHmmss") + "_" + new Random().nextInt(100000);
//        String dirs = common.getSystem("RESOURCE.TEMP.PATH") + "/" + filesdir;

        if (fileBean.getImg_host().endsWith("/")) {
            fileBean.setImg_host(fileBean.getImg_host() + filesdir + "/");
            fileBean.setPath(fileBean.getPath()+ filesdir + "/");
        } else {
            fileBean.setImg_host(fileBean.getImg_host() + "/" + filesdir);
            fileBean.setPath(fileBean.getPath()+ "/" + filesdir);
        }
        OSS ossClient = null;
        try{
            String fileName = fileBean.getPath()+"/"+fileBean.getFile_name();
            if(fileName.startsWith("/")){
                fileName = fileName.substring(1);
            }
            fileBean.setMd5(md5);

            ossClient = new OSSClientBuilder().build(common.getSystem("ALIYUN.ENDPOINT"), common.getSystem(
                    "ACCESSKEYID"), common.getSystem("ACCESSKEYSECRET"));
            PutObjectResult result = ossClient.putObject(common.getSystem("ALIYUN.BUCKETNAME"),
                    fileName, inputStream);
            if(StringUtils.isNotBlank(result.getETag())){

                int exc = baseRep.insertTemp(fileBean);
                fileBean.setId("T"+fileBean.getId());
                if (exc == 1) {
                    return fileBean;
                }
            }else{
                return null;
            }
        }catch (Exception e){
            logger.error("临时文件上传失败：",e);
        }

        return null;
    }

    @Override
    public boolean close() {
        return true;
    }

    @Override
    public String exeFile(String id, String path) {
        return exeFile(id, path, "1", OperType.getValue(OperType.BACKGROUND), "系统管理员");
    }

    @Override
    public String exeFile(String id, String path, String oper_id, int oper_type, String oper_name) {
        if (id.startsWith("z")) {//已经在正式中存在，直接下一个
            return id.replace("z", "");
        }
        if(!id.startsWith("z")&&!id.startsWith("T")){
            return id;
        }
        id = id.replace("T","");
        FileBean fileBean = baseRep.getTempFile(id);
        logger.debug("fileBean:" + fileBean);
        if (StringUtils.isBlank(fileBean.getFile_name())) {
            return "";
        }

        InputStream inputStream = null;
        OSS ossClient = null;
        try {

//            System.out.println(common.getSystem("ALIYUN.ENDPOINT") + "---" + common.getSystem("ACCESSKEYID") + "---" + common.getSystem("ACCESSKEYSECRET"));
            ossClient = new OSSClientBuilder().build(common.getSystem("ALIYUN.ENDPOINT"), common.getSystem(
                    "ACCESSKEYID"), common.getSystem("ACCESSKEYSECRET"));
            path = path.endsWith("/")?path.substring(0,path.length()-1):path;
            String fileName = path+"/"+fileBean.getFile_name();
            if(fileName.startsWith("/")){
                fileName = fileName.substring(1);
            }

            String tpaths = (fileBean.getPath().endsWith("/")?fileBean.getPath():fileBean.getPath()+"/");
            if(tpaths.startsWith("/")){
                tpaths = tpaths.substring(1);
            }
            CopyObjectResult result = ossClient.copyObject(common.getSystem("ALIYUN.BUCKETNAME.TEMP"), tpaths+fileBean.getFile_name(),common.getSystem("ALIYUN.BUCKETNAME"), fileName);

            logger.debug("结果：",result);

            fileBean.setImg_host(common.getSystem("RESOURCE.IMGHOST") + path + "/");
            String zpath = path.startsWith("/")?path.substring(1):path;
            if(!zpath.endsWith("/")){
                zpath += "/";
            }
            fileBean.setPath(zpath);
            fileBean.setOper_name(oper_name);

            fileBean.setOper_id(oper_id);
            fileBean.setOper_type(oper_type);

            if (baseRep.insertFile(fileBean) != 1) {
                ossClient.deleteObject(common.getSystem("ALIYUN.BUCKETNAME.TEMP"),fileBean.getPath()+fileBean.getFile_name());
                return null;
            }

            return String.valueOf(fileBean.getId());
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        } finally {

            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }

    @Override
    public List<String> exeFile(List<String> ids, String path) {
        List<String> resultList = new ArrayList<>();
        for (int i = 0; i < ids.size(); i++) {
            resultList.add(exeFile(ids.get(i), path, "1", OperType.getValue(OperType.BACKGROUND), "系统管理员"));
        }
        return resultList;
    }

    @Override
    public List<String> exeFile(List<String> ids, String path, String oper_id, int oper_type, String oper_name) {
        List<String> list = new ArrayList<>();
        for (int i = 0; i < ids.size(); i++) {
            String id = exeFile(ids.get(i), path, oper_id, oper_type, oper_name);
            if(id != null&&!"".equals(id)){
                list.add(id);
            }
        }
        return list;
    }

    @Override
    public void createPart(PartBean partBean) throws Exception {
        super.createPart(partBean);

        //根据文件md5值进行校验是否已经
        System.out.println("=====:"+common.getSystem("ALIYUN.ENDPOINT"));
        if (StringUtils.isBlank(partBean.getEndpoint())) {
            partBean.setEndpoint(common.getSystem("ALIYUN.ENDPOINT"));
        }

        if (StringUtils.isBlank(partBean.getAccessKeyId())) {
            partBean.setAccessKeyId(common.getSystem("ACCESSKEYID"));
        }

        if (StringUtils.isBlank(partBean.getAccessKeySecret())) {
            partBean.setAccessKeySecret(common.getSystem("ACCESSKEYSECRET"));
        }

        if (StringUtils.isBlank(partBean.getBucketName())) {
            partBean.setBucketName(common.getSystem("ALIYUN.BUCKETNAME.TEMP"));
        }

        ClientBuilderConfiguration conf = new ClientBuilderConfiguration();
//        conf.setIdleConnectionTime(3000);
        OSS client = new OSSClientBuilder().build(partBean.getEndpoint(), partBean.getAccessKeyId(),
                partBean.getAccessKeySecret(), conf);
        partBean.setOss(client);
        if(partBean.getUploadId() == null || "".equals(partBean.getUploadId())){
            partBean.setUploadId(claimUploadId(partBean));
        }
    }

    @Override
    public void uploadPart(PartBean partBean) throws Exception {
        super.uploadPart(partBean);
        UploadPartRequest uploadPartRequest = new UploadPartRequest();
        uploadPartRequest.setBucketName(partBean.getBucketName());
        uploadPartRequest.setKey(partBean.getKey());
        uploadPartRequest.setUploadId(partBean.getUploadId());
        uploadPartRequest.setInputStream(partBean.getInstream());
        uploadPartRequest.setPartSize(partBean.getPartSize());
        uploadPartRequest.setPartNumber(partBean.getPartNumber()+1);

        logger.debug("partBean:"+partBean.toString());
        logger.debug("uploadPartRequest:"+uploadPartRequest.toString());
        UploadPartResult uploadPartResult = partBean.getOss().uploadPart(uploadPartRequest);
        logger.debug("上传完成？");
        List list = redisUtil.getValueObject("upload" + partBean.getUploadId(),List.class);
        if(list == null){
            list = new ArrayList();
        }
        logger.debug("分片上传记录list:"+list.size()+"-==-"+partBean.getUploadId());
        list.add(uploadPartResult.getPartETag());
        logger.debug("分片上传记录list:"+list);
        redisUtil.setKeyObject("upload" + partBean.getUploadId(), list, 1L, TimeUnit.DAYS);
    }

    @Override
    public void closePart(PartBean partBean) throws Exception {
        super.closePart(partBean);

        try {
            completeMultipartUpload(partBean);
            redisUtil.deleteKey("upload" + partBean.getUploadId());
        } catch (Exception e) {
            throw new Exception("关闭失败");
        } finally {
            if (partBean.getOss() != null) {
                partBean.getOss().shutdown();
            }
        }

    }

    private void completeMultipartUpload(PartBean partBean) {

        List list = redisUtil.getValueObject("upload" + partBean.getUploadId(), List.class);
        logger.debug("list:"+list);
        // Make part numbers in ascending order
        Collections.sort(list, new Comparator<PartETag>() {

            @Override
            public int compare(PartETag p1, PartETag p2) {
                return p1.getPartNumber() - p2.getPartNumber();
            }

        });
        logger.debug("list:"+list);
        System.out.println("Completing to upload multiparts\n");
        CompleteMultipartUploadRequest completeMultipartUploadRequest =
                new CompleteMultipartUploadRequest(partBean.getBucketName(), partBean.getKey(),
                        partBean.getUploadId(), list);
        partBean.getOss().completeMultipartUpload(completeMultipartUploadRequest);

        CopyObjectResult result = partBean.getOss().copyObject(partBean.getBucketName(), partBean.getKey(), partBean.getBucketName(), partBean.getPath()+partBean.getKey());
        System.out.println("ETag: " + result.getETag() + " LastModified: " + result);
        partBean.getOss().deleteObject(partBean.getBucketName(), partBean.getKey());
    }

    private String claimUploadId(PartBean partBean) {
        InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest(partBean.getBucketName(),
                partBean.getKey());
        InitiateMultipartUploadResult result = partBean.getOss().initiateMultipartUpload(request);
        return result.getUploadId();
    }

}